﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CookComputing.XmlRpc;
using System.Web.Configuration;
using JeanFish.Blog.Business;
using System.Configuration;
using System.IO;
using JeanFish.Blog.Storage;

namespace JeanFish.Blog.XmlRpc
{
    public sealed class BlogApiHandler : XmlRpcService, IMetaWeblog, IBlogger, IMovableType, IWordPress
    {
        static BlogApiHandler()
        {
            Task.WaitAll(LoadBlog());
        }
        static async Task LoadBlog()
        {
            BlogService.SetBlogProvider(BlogProviderHelper.GetDefaultDataProvider("jeanFish.blog/data"), BlogProviderHelper.GetDefaultMediaProvider("jeanFish.blog/media"));
            await BlogService.Current.LoadBlogAsync();
            Blog = BlogService.Current.Blog;
        }
        static Business.Blog Blog;
        public BlogApiHandler()
        {
            if (Blog == null) LoadBlog();
        }
        
        private void SetResponseStatus(int statusCode, string description, int? subStatusCode = null)
        {
            Context.Response.Charset = "utf-8";
            Context.Response.StatusCode = statusCode;
            Context.Response.StatusDescription = description;
            if (subStatusCode.HasValue) Context.Response.SubStatusCode = subStatusCode.Value;
        }
        const string wlw16Appkey = "0123456789ABCDEF";
        const string wlw14Appkey = "ffffffabffffffce6dffffff93ffffffac29ffffffc9fffffff826ffffffdeffffffc9ffffffe43c0b763036ffffffa0fffffff3ffffffa963377716";
        private bool Authenticate(string username, string password, string appKey, string blogId, string postId)
        {
            if (!string.IsNullOrEmpty(appKey))
            {
                if (!(appKey==wlw14Appkey||appKey==wlw16Appkey))
                {
                    SetResponseStatus(501, Resources.ClientNotSupportedError);
                    throw new Exception(Resources.ClientNotSupportedError);
                }
            }
            if (!string.IsNullOrEmpty(blogId))
            {
                if (Blog.ID != Guid.Parse(blogId))
                {
                    SetResponseStatus(404, Resources.SpecifiedBlogNotExist);
                    throw new Exception(Resources.SpecifiedBlogNotExist);
                }
            }
            if (Blog.Onwer.Validate(username, password))
            {
                return true;
            }
            SetResponseStatus(401, Resources.AuthenticationFaild);
            throw new Exception(Resources.AuthenticationFaild);

        }
        #region MetaWeblog
        async Task<bool> IMetaWeblog.EditPostAsync(string postid, string username, string password, Post post, bool publish)
        {
            this.Authenticate(username, password, null, null, postid);
            Guid postId = Guid.Parse(postid);
            var p = await Blog.GetPostAsync(postId);
            if (p == null)
            {
                throw new Exception(Resources.InvalidPostId);
            }
            p.Title = post.Title;
            p.Text = post.Description;
            p.AcceptChanges();
            return true;
        }

        CategoryInfo[] IMetaWeblog.GetCategories(string blogid, string username, string password)
        {
            throw new NotImplementedException();
        }

        Post IMetaWeblog.GetPost(string postid, string username, string password)
        {
            this.Authenticate(username, password, null, null, postid);
            Guid postId = Guid.Parse(postid);
            var p = Blog.GetPostAsync(postId).Result;
            if (p == null)
            {
                SetResponseStatus(404, Resources.InvalidPostId);
                throw new Exception(Resources.InvalidPostId);
            }
            return new Post()
            {
                PostID = p.ID.ToString("N"),
                Title = p.Title,
                Description = p.Text,
                UserID = p.Author.ID.ToString("N"),
                DateCreated = p.CreatedTime,
            };
        }

        Post[] IMetaWeblog.GetRecentPosts(string blogid, string username, string password, int numberOfPosts)
        {
            Authenticate(username, password, null, blogid, null);
            return Blog.ListPosts(new Paging(0,numberOfPosts)).Result.Select(p => new Post()
            {
                PostID = p.ID.ToString("N"),
                Title = p.Title,
                Description = p.Text,
                UserID = p.Author.ID.ToString("N"),
                DateCreated = p.CreatedTime,
            }).ToArray();
        }

        string IMetaWeblog.NewPost(string blogid, string username, string password, Post post, bool publish)
        {
            Authenticate(username, password, null, blogid, null);
            var newPost = new Business.Post(Blog)
            {
                Title = post.Title,
                Text = post.Description,
                //XXX=post.Categories
            };
            newPost.AcceptChanges();
            return newPost.ID.ToString("N");
        }

        UrlData IMetaWeblog.NewMediaObject(string blogid, string username, string password, FileData file)
        {
            Authenticate(username, password, null, blogid, null);
            string fileName = Guid.NewGuid().ToString("N").ToLower() + Path.GetExtension(file.Name);
            var uri = BlogService.Current.SaveMediaAsync(Blog, fileName, new MemoryStream(file.Bits));
            return new UrlData()
            {
                Url=uri.ToString()
            };
        }
        #endregion
        #region Blogger
        bool IBlogger.DeletePost(string appKey, string postid, string username, string password, bool publish)
        {
            Authenticate(username, password, appKey, null, postid);
            Guid postId = Guid.Parse(postid);
            var p = Blog.GetPostAsync(postId).Result;
            if (p == null)
            {
                SetResponseStatus(404, Resources.InvalidPostId);
                throw new Exception(Resources.InvalidPostId);
            }
            p.Delete();
            p.AcceptChanges();
            return true;
        }

        object IBlogger.EditPost(string appKey, string postid, string username, string password, string content, bool publish)
        {
            throw new NotImplementedException();
        }

        Category[] IBlogger.GetCategories(string blogid, string username, string password)
        {
            throw new NotImplementedException();
        }

        Post IBlogger.GetPost(string appKey, string postid, string username, string password)
        {
            throw new NotImplementedException();
        }

        Post[] IBlogger.GetRecentPosts(string appKey, string blogid, string username, string password, int numberOfPosts)
        {
            throw new NotImplementedException();
        }

        string IBlogger.GetTemplate(string appKey, string blogid, string username, string password, string templateType)
        {
            throw new NotImplementedException();
        }

        UserInfo IBlogger.GetUserInfo(string appKey, string username, string password)
        {
            throw new NotImplementedException();
        }

        BlogInfo[] IBlogger.GetUsersBlogs(string appKey, string username, string password)
        {
            Authenticate(username, password, appKey, null, null);
            return new BlogInfo[] {
                new BlogInfo()
                {
                    BlogID=Blog.ID.ToString("N"),
                    BlogName=Blog.Name,
                    Url=ConfigurationManager.AppSettings["blogUrl"]
                }
            };
        }

        string IBlogger.NewPost(string appKey, string blogid, string username, string password, string content, bool publish)
        {
            throw new NotImplementedException();
        }

        bool IBlogger.SetTemplate(string appKey, string blogid, string username, string password, string template, string templateType)
        {
            throw new NotImplementedException();
        }
        #endregion
        #region MovableType
        Category[] IMovableType.GetCategoryList(string blogid, string username, string password)
        {
            throw new NotImplementedException();
        }

        Category[] IMovableType.GetPostCategories(string postid, string username, string password)
        {
            throw new NotImplementedException();
        }

        PostTitle[] IMovableType.GetRecentPostTitles(string blogid, string username, string password, int numberOfPosts)
        {
            throw new NotImplementedException();
        }

        TrackbackPing[] IMovableType.GetTrackbackPings(string postid)
        {
            throw new NotImplementedException();
        }

        bool IMovableType.PublishPost(string postid, string username, string password)
        {
            throw new NotImplementedException();
        }

        bool IMovableType.SetPostCategories(string postid, string username, string password, Category[] categories)
        {
            Authenticate(username, password, null, null, postid);
            Guid postId = Guid.Parse(postid);
            var p = Blog.GetPostAsync(postId);
            if (p == null)
            {
                SetResponseStatus(404, Resources.InvalidPostId);
                throw new Exception(Resources.InvalidPostId);
            }
            return true;
        }

        string[] IMovableType.SupportedMethods()
        {
            throw new NotImplementedException();
        }
        #endregion
        #region WordPress
        BlogInfo[] IWordPress.GetUsersBlogs(string username, string password)
        {
            throw new NotImplementedException();
        }

        Tag[] IWordPress.GetTags(string blogId, string username, string password)
        {
            throw new NotImplementedException();
        }

        Author[] IWordPress.GetAuthors(string blogId, string username, string password)
        {
            throw new NotImplementedException();
        }

        Option[] IWordPress.GetOptions(string blogId, string username, string password, params Option[] options)
        {
            throw new NotImplementedException();
        }

        Option[] IWordPress.SetOptions(string blogId, string username, string password, params Option[] options)
        {
            throw new NotImplementedException();
        }

        PostStatus[] IWordPress.GetPostStatusList(string blogId, string username, string password)
        {
            throw new NotImplementedException();
        }

        PostFormat[] IWordPress.GetPostFormats(string blogId, string username, string password, params PostFormatsFilter[] filters)
        {
            throw new NotImplementedException();
        }

        Comment[] IWordPress.GetComments(string blogId, string username, string password, CommentQuery query)
        {
            throw new NotImplementedException();
        }

        CommentCount IWordPress.GetCommentCount(string blogId, string username, string password, string postId)
        {
            throw new NotImplementedException();
        }

        Comment IWordPress.GetComment(string blogId, string username, string password, int commentId)
        {
            throw new NotImplementedException();
        }

        bool IWordPress.DeleteComment(string blogId, string username, string password, int commentId)
        {
            throw new NotImplementedException();
        }

        bool IWordPress.EditComment(string blogId, string username, string password, int commentId, Comment comment)
        {
            throw new NotImplementedException();
        }

        int IWordPress.NewComment(string blogId, string username, string password, int postId, Comment comment)
        {
            throw new NotImplementedException();
        }

        CommentStatus[] IWordPress.GetCommentStatusList(string blogId, string username, string password)
        {
            throw new NotImplementedException();
        }

        PageStatus[] IWordPress.GetPageStatusList(string blogId, string username, string password)
        {
            throw new NotImplementedException();
        }

        PageTemplate[] IWordPress.GetPageTemplates(string blogId, string username, string password)
        {
            throw new NotImplementedException();
        }

        Page IWordPress.GetPage(string blogId, int pageId, string username, string password)
        {
            throw new NotImplementedException();
        }

        Page[] IWordPress.GetPages(string blogId, string username, string password, int maxPages)
        {
            throw new NotImplementedException();
        }

        Page[] IWordPress.GetPageList(string blogId, string usernmae, string password)
        {
            throw new NotImplementedException();
        }

        int IWordPress.NewPage(string blogId, string username, string password, Page content, bool publish)
        {
            throw new NotImplementedException();
        }

        bool IWordPress.DeletePage(string blogId, string username, string password, int pageId)
        {
            throw new NotImplementedException();
        }

        int IWordPress.EditPage(string blogId, string username, string password, Page content, bool publish)
        {
            throw new NotImplementedException();
        }

        Category[] IWordPress.GetCategories(string blogId, string username, string password)
        {
            throw new NotImplementedException();
        }

        int IWordPress.NewCategory(string blogId, string username, string password, Category category)
        {
            throw new NotImplementedException();
        }

        bool IWordPress.DeleteCategory(string blogId, string username, string password, int categoryId)
        {
            throw new NotImplementedException();
        }

        SuggestedCategory[] IWordPress.SuggestCategories(string blogId, string username, string password, string category, int maxResult)
        {
            throw new NotImplementedException();
        }

        FileInfo IWordPress.UploadFile(string blogId, string username, string password, FileData data)
        {
            throw new NotImplementedException();
        }

        MediaItem IWordPress.GetMediaItem(string blogId, string username, string password, int attachmentId)
        {
            throw new NotImplementedException();
        }

        MediaItem[] IWordPress.GetMediaLibrary(string blogId, string username, string password, MediaFilter filer)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
